﻿using System.Windows.Controls.Ribbon;

namespace MyCusTools;

[ComVisible(true)]
public class MyRibbon : ExcelRibbon
{

    #region ExcelRibbon类的函数-自动加载xml和image
    public override string GetCustomUI(string RibbonID) // Excel加载插件时自动调用
    {
        return RibbonResources.Ribbon;
    }

    public override object? LoadImage(string imageId) // 首次需要显示图标时才被调用，属于懒加载模式
    {
        return RibbonResources.ResourceManager.GetObject(imageId);
    }
    #endregion

    #region  Jupyter Ctp窗口显示逻辑  "JupyterLab"按钮得回调函数"Jupyter_Show"
    // 解决不同窗口不能显示jupyter自定义窗口问题
    // 使用Dictionary<int, CustomTaskPane>按窗口句柄存储任务窗格，确保每个窗口有独立实例
    private Dictionary<int, CustomTaskPane> _ctpDict = new Dictionary<int, CustomTaskPane>();
    public void Jupyter_Show(IRibbonControl control)
    {
        Excel.Application excelApp = (Excel.Application)ExcelDnaUtil.Application;
        Excel.Window activeWindow = excelApp.ActiveWindow;
        int hwnd = activeWindow.Hwnd;

        CleanUpClosedWindows(excelApp);

        if (!_ctpDict.TryGetValue(hwnd, out CustomTaskPane ctp))
        {
            Jupyter_UC jupyterUc = new Jupyter_UC();
            ctp = CustomTaskPaneFactory.CreateCustomTaskPane(jupyterUc, "Jupyter");
            ctp.DockPosition = MsoCTPDockPosition.msoCTPDockPositionRight;
            _ctpDict[hwnd] = ctp;
        }

        ctp.Visible = !ctp.Visible;
    }

    // 方法会在每次操作前清理已关闭窗口的任务窗格，防止内存泄漏
    // 当检测到窗口关闭时，调用ctp.Delete()显式释放资源，并从字典中移除
    private void CleanUpClosedWindows(Excel.Application excelApp)
    {
        var closedHwnds = new List<int>();
        foreach (var hwnd in _ctpDict.Keys.ToList())
        {
            bool windowExists = false;
            foreach (Excel.Window window in excelApp.Windows)
            {
                if (window.Hwnd == hwnd)
                {
                    windowExists = true;
                    break;
                }
            }
            if (!windowExists)
            {
                if (_ctpDict.TryGetValue(hwnd, out CustomTaskPane ctp))
                {
                    ctp.Delete();
                    closedHwnds.Add(hwnd);
                }
            }
        }

        foreach (var hwnd in closedHwnds)
        {
            _ctpDict.Remove(hwnd);
        }
    }
    #endregion


}


